﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.IO;
using System.Drawing;
using System.Threading;




namespace WindowsGame1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        Vector2 vect;
        SpriteBatch spriteBatch;
        List<EtreVivant> listEtreVivant;
        ListEtreVivant[,] lev;
        Vector2 spritePosition = Vector2.Zero;
        Vector2[,] Positions;
        Texture2D[,] listText;
        Form f;
        MouseState posSouris; 
        KeyboardState curState;
        Formtest ft;
        Texture2D TextOri;
        float _rotationInDegrees = 0.0f;
        //BasicEffect effect;
       // float _rotationInDegrees = 0.0f;
        float _zoom = 1F;
        
        //public float zoom
        //{
        //    get { return _zoom; }
        //    set { _zoom = value; }
        //}
        //float _avance = 3.94999743f;
        static float _translationX = 0.0f;
        static float _translationY = 0.0f;
        float Tx = 0;
        float Ty = 0;
        RenderTarget2D _2Dmap;
        RenderTarget2D _mapTransformation;
        readonly Vector2 _scale = new Vector2(1.0f, 0.5f);
        // centre de ma map (ma rotation se fera en fonction de ce point).
        readonly Vector2 _mapOrigin = new Vector2(-(TileCount * TileSize) / 2.0f, (TileCount * TileSize) / 2.0f);
        const int TileCount = 10;
        const int TileSize = 200;
        readonly float _rotationAngle = 0.7854f; // = 45°.
        //float RotateZ = 0.0f;
        public Game1()
        {
            // On crée le graphic pour dessiner sur la page xna
            graphics = new GraphicsDeviceManager(this);
            
            Content.RootDirectory = "Content";
            // On change la taille de la page xna
            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
            graphics.IsFullScreen = false;
            graphics.ApplyChanges();
            
            graphics.PreferMultiSampling = true;
            IntPtr ptr = this.Window.Handle;
            // On transforme la page xna en windowsform
            f = (System.Windows.Forms.Form)System.Windows.Forms.Control.FromHandle(ptr);
            // On active la sourie sur la page xna
            this.IsMouseVisible = true;
            //f.Refresh();
            Microsoft.Xna.Framework.Point p = this.Window.ClientBounds.Location;
            ft = new Formtest();
            ft.Location = new System.Drawing.Point(5,84);
            // On met la position de départ de la form en mode manuel pour la régler manuellement
            f.StartPosition = FormStartPosition.Manual;
            // On règle la position de départ sur l'écran de la form
            f.Location = new System.Drawing.Point(5, 5);
            // On enlève la barre d'outil avec les icone quitter agrandir et réduire
            f.FormBorderStyle = FormBorderStyle.None;
            ft.FormBorderStyle = FormBorderStyle.None;
            ft.Show();
            FormTemps ftemps = new FormTemps();
            ftemps.Location = new System.Drawing.Point(283,0);
            ftemps.FormBorderStyle = FormBorderStyle.None;
            ftemps.Show();
           
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent(){
        
            
            //this.GraphicsDevice.Present();
            listEtreVivant = new List<EtreVivant>();
            lev = new ListEtreVivant[12,12];
            // On initialise le graphic pour dessiné dessus
            spriteBatch = new SpriteBatch(this.GraphicsDevice);
            // On va récupérer l'image
            Image im = Image.FromFile(Application.StartupPath + @"\Content\Carré-blog1.jpg");
            // On redimentionne l'image
            Bitmap img = new Bitmap(im, new Size(400, 400));
            // On créer le tableau des 144 cases (texture qui permette de mettre des image)
            listText = new Texture2D[12, 12];
            // On créer les 144 positions de chaque texture (coordonnées)
            Positions = new Vector2[12, 12];
            for (int i = 0; i < 12; i++)
            {
                for (int j = 0; j < 12; j++)
                {
                    
                    using (MemoryStream s = new MemoryStream())
                    {
                        img.Save(s, System.Drawing.Imaging.ImageFormat.Jpeg);
                        s.Seek(0, SeekOrigin.Begin);
                        // On met l'image dans la texture
                        listText[i, j] = Texture2D.FromStream(this.spriteBatch.GraphicsDevice, s);
                    }
                    listEtreVivant = new List<EtreVivant>();
                    // On créé la liste des êtres vivants qui sont dans une case
                    lev[i, j] = new ListEtreVivant(listEtreVivant);
                    //listText[i, j] = Content.Load<Texture2D>("Carré-blog1");
                }
            }
            //im = Image.FromFile(Application.StartupPath + @"\Content\Carré-blog1.jpg");
            //img = new Bitmap(im, new Size(100, 100));
            //using (MemoryStream s = new MemoryStream())
            //{
            //    img.Save(s, System.Drawing.Imaging.ImageFormat.Jpeg);
            //    s.Seek(0, SeekOrigin.Begin);
            //    TextOri = Texture2D.FromStream(this.spriteBatch.GraphicsDevice, s);
            //}
           // On crée la map 2D
            _2Dmap = new RenderTarget2D(GraphicsDevice, TileCount * TileSize, TileCount * TileSize);
            // On crée la map qui va permettre de transformer la map 2d en 3d iso
            _mapTransformation = new RenderTarget2D(GraphicsDevice, 2 * (TileCount * TileSize), 2 * (TileCount * TileSize));
        }
  
        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                this.Exit();
            
           
            // Initialisation des actions avec la souries
            posSouris = Mouse.GetState();
            // Initialisation des actions avec le clavier
            curState = Keyboard.GetState();
            
        
            if(curState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Z))
            {
                //On zoome
                _zoom += 0.02F;
               
            }
            if (curState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.X))
            {
                // on dézoome
                if (_zoom > 0.421f)
                _zoom -= 0.02F;
                
            }
            if (curState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Right))
            {
                if (!ft.Full3DIso)
                {
                    // On se déplace vers la gauche en 2d
                    if (_translationX > -(listText[0, 0].Width * (12 - (2F / _zoom))) * _zoom)
                        _translationX -= 10.0f * _zoom;
                }
                else
                {
                    // On se déplace vers la gauche en 3d iso
                    if (_translationX > -(listText[0, 0].Width * (12 - (5 / _zoom))) * _zoom)
                        _translationX -= 10.0f * _zoom;
                }

            }
            if (curState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Left))
            {
                // On se déplace vers la droite
                if (_translationX < 0)
                _translationX+= 10.0f*_zoom;
            }
            if (curState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Down))
            {
                if (!ft.Full3DIso)
                {
                    // On se déplce vers le bas en 2D
                    if (_translationY > -(listText[0, 0].Height * (12 - (1.5F / _zoom))) * _zoom)
                        _translationY -= 10.0f * _zoom;
                }
                else
                {
                    // On se déplce vers le bas en 3D iso
                    if (_translationY > -(listText[0, 0].Height * (12 - (5 / _zoom))) * _zoom)
                        _translationY -= 10.0f * _zoom;
                }
            }
            if (curState.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Up))
            {
                // On se déplace vers le haut
                if (_translationY < 0)
                _translationY+=10.0f*_zoom;
            }
         
            if (posSouris.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
            {
               // Microsoft.Xna.Framework.Point p = new Microsoft.Xna.Framework.Point(_mapTransformation.Bounds.Width,_mapTransformation.Bounds.Height);
                if (ft.ImageTerrain != null)
                {
                    for (int i = 0; i < 12; i++)
                    {
                        for (int j = 0; j < 12; j++)
                        {
                            
                            //Vector2 vector = convertScreenCoordInTileCoord(posSouris.X, posSouris.Y);
                            Vector2 pos = new Vector2(posSouris.X - _translationX, posSouris.Y - _translationY);
                            //listText[i, j].GraphicsDevice.SetRenderTarget(null);
                            // On cherche la position de la case à sélectionner (peut se faire qu'en 2D)
                            if (pos.X >= Positions[i, j].X && pos.X <= (Positions[i, j].X + listText[i, j].Width * _zoom ) && pos.Y >= Positions[i, j].Y && pos.Y <= (Positions[i, j].Y + listText[i, j].Height * _zoom ))
                            {

                                Image im = ft.ImageTerrain;
                                Bitmap img = new Bitmap(im, new Size(400, 400));
                                using (MemoryStream s = new MemoryStream())
                                {
                                    img.Save(s, System.Drawing.Imaging.ImageFormat.Jpeg);
                                    s.Seek(0, SeekOrigin.Begin);
                                    // On remplace l'image du terrain sélectionné pour la case ou on a cliqué avec la sourie
                                    listText[i, j] = Texture2D.FromStream(this.spriteBatch.GraphicsDevice, s);
                                }
                            }
                        }
                    }
                }
                if (ft.ImageEtre != null)
                {
                    for (int i = 0; i < 12; i++)
                    {
                        for (int j = 0; j < 12; j++)
                        {

                            //Vector2 vector = convertScreenCoordInTileCoord(posSouris.X, posSouris.Y);
                            Vector2 pos = new Vector2(posSouris.X - _translationX, posSouris.Y - _translationY);
                            //listText[i, j].GraphicsDevice.SetRenderTarget(null);
                            if (pos.X >= Positions[i, j].X && pos.X <= (Positions[i, j].X + listText[i, j].Width * _zoom) && pos.Y >= Positions[i, j].Y && pos.Y <= (Positions[i, j].Y + listText[i, j].Height * _zoom))
                            {

                                EtreVivant e = new EtreVivant(ft.nomEtre, ft.ImageEtre);
                                // Ajout a la liste de l'être vivant
                                lev[i, j].getListEtre().Add(e);
                                for (int t = 0; t < lev[i, j].getListEtre().Count; t++)
                                {
                                    Image im = lev[i, j].getListEtre()[t].getImageEtre();
                                    Bitmap img = new Bitmap(im, new Size(100, 100));
                                    using (MemoryStream s = new MemoryStream())
                                    {

                                        img.Save(s, System.Drawing.Imaging.ImageFormat.Png);
                                        s.Seek(0, SeekOrigin.Begin);
                                        // Ajout de l'image sur la texture de l'être vivant
                                        lev[i, j].getListEtre()[t].setTexture(Texture2D.FromStream(this.spriteBatch.GraphicsDevice, s));
                                    }
                                }
                            }
                        }
                    }
                }
                Thread.Sleep(300);
                //GraphicsDevice.SetRenderTarget(null);
            }
         
            if (!ft.Full3DIso)
            {
                // redimentionnement pour ne pas dépassé en fonction de la taille total du plateau en 2D
                if (_translationX < -(listText[0, 0].Width * (12 - (2 / _zoom))) * _zoom)
                    _translationX = -(listText[0, 0].Width * (12 - (2 / _zoom))) * _zoom;
                if (_translationY < -(listText[0, 0].Height * (12 - (1.5F / _zoom))) * _zoom)
                    _translationY = -(listText[0, 0].Height * (12 - (1.5F / _zoom))) * _zoom;
            }
            else
            {
                // redimentionnement pour ne pas dépassé en fonction de la taille total du plateau en 3D iso
                if (_translationX < -(listText[0, 0].Width * (12 - (5 / _zoom))) * _zoom)
                    _translationX = -(listText[0, 0].Width * (12 - (5 / _zoom))) * _zoom;
                if (_translationY < -(listText[0, 0].Height * (12 - (5 / _zoom))) * _zoom)
                    _translationY = -(listText[0, 0].Height * (12 - (5 / _zoom))) * _zoom;
            }
            base.Update(gameTime);
        }

        /// <summary>z
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
                GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.DarkOrange);
            //On teste si la case 3D isométrique est sélectionné oui 3D iso non 2D
                if (ft.Full3DIso)
                    GraphicsDevice.SetRenderTarget(_2Dmap);
                
                // On démarre l'action sur le graphic on appel getMatrix() pour le zoom et les déplacements
                spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, RasterizerState.CullNone, null, GetMatrix(GraphicsDevice));
                // On pivote les images des êtres vivant sur 45° poour donner l'impression qu'ils sont debout sur la case en 3D iso
                float rad = -0.424999744F;
               
                int largeur2 = 0;
                int longueur = 0;
                for (int i = 0; i < 12; i++)
                {
                    largeur2 = 0;
                    for (int j = 0; j < 12; j++)
                    {
                            // On crée les coordonnées par case (positions)
                            Positions[i, j] = new Vector2(largeur2, longueur);
                           
                            // On dessine les cases du plateau
                            spriteBatch.Draw(listText[i, j], Positions[i, j], Microsoft.Xna.Framework.Color.FromNonPremultiplied(255,255,255, 255));
                            largeur2 += listText[0, 0].Width;
                            //Positions[i, j].X = Positions[i, j].X * _zoom;
                            //Positions[i, j].Y = Positions[i, j].Y * _zoom;
                    }
                    longueur += listText[0, 0].Height;
                }

                spriteBatch.End();
                spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, RasterizerState.CullNone, null, GetMatrix(GraphicsDevice));
                for (int i = 0; i < 12; i++)
                {
                    largeur2 = 0;
                    for (int j = 0; j < 12; j++)
                    {
                        // On parcours la liste des êtres vivants contenu dans une case
                        for (int k = 0; k < lev[i, j].getListEtre().Count; k++)
                        {
                            // On dessine les êtres sur la case 9 images au maximum
                            if (k == 0)
                                spriteBatch.Draw(lev[i, j].getListEtre()[k].getTexture(), new Vector2(Positions[i, j].X + 0, Positions[i, j].Y + 0), null, Microsoft.Xna.Framework.Color.FromNonPremultiplied(255, 255, 255, 255), rad, new Vector2(-0, -110), 0.8F, SpriteEffects.None, 0);
                            if (k == 1)
                                spriteBatch.Draw(lev[i, j].getListEtre()[k].getTexture(), new Vector2(Positions[i, j].X + 0, Positions[i, j].Y + 100), null, Microsoft.Xna.Framework.Color.FromNonPremultiplied(255, 255, 255, 255), rad, new Vector2(-0, -110), 0.8F, SpriteEffects.None, 0);
                            if (k == 2)
                                spriteBatch.Draw(lev[i, j].getListEtre()[k].getTexture(), new Vector2(Positions[i, j].X + 100, Positions[i, j].Y + 0), null, Microsoft.Xna.Framework.Color.FromNonPremultiplied(255, 255, 255, 255), rad, new Vector2(-0, -110), 0.8F, SpriteEffects.None, 0);
                            if (k == 3)
                                spriteBatch.Draw(lev[i, j].getListEtre()[k].getTexture(), new Vector2(Positions[i, j].X + 100, Positions[i, j].Y + 100), null, Microsoft.Xna.Framework.Color.FromNonPremultiplied(255, 255, 255, 255), rad, new Vector2(-0, -110), 0.8F, SpriteEffects.None, 0);
                            if (k == 4)
                                spriteBatch.Draw(lev[i, j].getListEtre()[k].getTexture(), new Vector2(Positions[i, j].X + 200, Positions[i, j].Y + 0), null, Microsoft.Xna.Framework.Color.FromNonPremultiplied(255, 255, 255, 255), rad, new Vector2(-0, -110), 0.8F, SpriteEffects.None, 0);
                            if (k == 5)
                                spriteBatch.Draw(lev[i, j].getListEtre()[k].getTexture(), new Vector2(Positions[i, j].X + 200, Positions[i, j].Y + 100), null, Microsoft.Xna.Framework.Color.FromNonPremultiplied(255, 255, 255, 255), rad, new Vector2(-0, -110), 0.8F, SpriteEffects.None, 0);
                            if (k == 6)
                                spriteBatch.Draw(lev[i, j].getListEtre()[k].getTexture(), new Vector2(Positions[i, j].X + 0, Positions[i, j].Y + 200), null, Microsoft.Xna.Framework.Color.FromNonPremultiplied(255, 255, 255, 255), rad, new Vector2(-0, -110), 0.8F, SpriteEffects.None, 0);
                            if (k == 7)
                                spriteBatch.Draw(lev[i, j].getListEtre()[k].getTexture(), new Vector2(Positions[i, j].X + 100, Positions[i, j].Y + 200), null, Microsoft.Xna.Framework.Color.FromNonPremultiplied(255, 255, 255, 255), rad, new Vector2(-0, -110), 0.8F, SpriteEffects.None, 0);
                            if (k == 8)
                                spriteBatch.Draw(lev[i, j].getListEtre()[k].getTexture(), new Vector2(Positions[i, j].X + 200, Positions[i, j].Y + 200), null, Microsoft.Xna.Framework.Color.FromNonPremultiplied(255, 255, 255, 255), rad, new Vector2(-0, -110), 0.8F, SpriteEffects.None, 0);
                        }
                        Positions[i, j].X = Positions[i, j].X * _zoom;
                        Positions[i, j].Y = Positions[i, j].Y * _zoom;
                    }
                }
               
                spriteBatch.End();
                if (ft.Full3DIso)
                {
                    //On transforme le plan 2D en 3D iso
                    GraphicsDevice.SetRenderTarget(_mapTransformation);
                    GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.DarkOrange);
                    spriteBatch.Begin();
                    // On dessine notre map en 2D en lui faisant faire une rotation de 45°.
                    spriteBatch.Draw(_2Dmap, Vector2.Zero, null, Microsoft.Xna.Framework.Color.White, _rotationAngle, _mapOrigin, 0.992F, SpriteEffects.None, 0);
                    spriteBatch.End();
                    // On revient sur notre plan de départ
                    GraphicsDevice.SetRenderTarget(null);
                    GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.DarkOrange);

                    spriteBatch.Begin();

                    // On dessine notre map transformée en appliquant un vecteur
                    // de redimentionnement (0.286 sur l'axe des abscisse et 0.16 sur l'axe des ordonnées).
                    vect = new Vector2(0.286F, 0.16F);
                    spriteBatch.Draw(_mapTransformation, Vector2.Zero, null, Microsoft.Xna.Framework.Color.White, 0, Vector2.Zero, vect, SpriteEffects.None, 0);
                    spriteBatch.End();
                }

               
            
            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }

        public Matrix GetMatrix(GraphicsDevice graphicsDevice)
        {
            Tx = _translationX;
            Ty = _translationY;
            //Matrix translateToOrigin = Matrix.CreateTranslation(-Tx, -Ty, 0);
            Matrix translateToOrigin = Matrix.CreateTranslation(0, 0, 0);
            //Microsoft.Xna.Framework.Matrix rotationMatrix = Microsoft.Xna.Framework.Matrix.CreateRotationZ(MathHelper.ToRadians(MathHelper.ToRadians(MathHelper.ToRadians(_rotationInDegrees))));
            //Matrix myMatrix = Matrix.CreateRotationX(RotateZ);
            // On crée le zoom 
            Matrix zoomMatrix = Matrix.CreateScale(_zoom,_zoom,_zoom);
            // On crée la translation
            Microsoft.Xna.Framework.Matrix translateBackToPosition = Microsoft.Xna.Framework.Matrix.CreateTranslation(Tx, Ty, 0);
            //Matrix compositeMatrix = translateToOrigin * rotationMatrix * zoomMatrix * translateBackToPosition;
            //On redimentionne en fonction des valeur
            Microsoft.Xna.Framework.Matrix compositeMatrix = zoomMatrix * translateBackToPosition * translateToOrigin;
            //Microsoft.Xna.Framework.Matrix compositeMatrix = zoomMatrix * translateToOrigin * rotationMatrix;
            // On renvoie la transformation
            return compositeMatrix;
        }

        //public Microsoft.Xna.Framework.Vector2 convertTileCoordInScreenCoord(float tileCoordX,float tileCoordY)
        //{
        //    Microsoft.Xna.Framework.Vector2 ScreenCord = new Microsoft.Xna.Framework.Vector2();
        //    ScreenCord.X = (tileCoordX - tileCoordY) * _2Dmap.Width / 2;
        //    ScreenCord.Y = (tileCoordX + tileCoordY) * _2Dmap.Height / 2;
 
        //    return ScreenCord;
        //}
        //public Vector2 convertScreenCoordInTileCoord(float screenCoordX,float screenCoordY)
        //{
        //    Vector2 TileCord = new Vector2();
        //    screenCoordX = screenCoordX - (_2Dmap.Width / 2);
        //    TileCord.X = (screenCoordY / _2Dmap.Height) + (screenCoordX / _2Dmap.Width);
        //    TileCord.Y = (screenCoordY / _2Dmap.Height) - (screenCoordX / _2Dmap.Width);
        //    return TileCord;
        //}
      
    }
}
